
import sys
import os
import binascii

def parse_intel_hex(fin):
	seg_addr = 0
	lin_addr = 0
	met_data = False
	data = bytearray()
	prev_addr = 0
	index = 0
	for line in fin:
		index += 1
		data_len = int(line[1:3], 16)
		rec_addr = int(line[3:7], 16)
		rec_type = int(line[7:9])

		if rec_type == 0:
			current_addr = (lin_addr << 16) + (seg_addr << 8) + rec_addr
			if met_data and current_addr > prev_addr:
				for i in range(current_addr - prev_addr):
					data.append(0xFF)

			met_data = True
			b = binascii.a2b_hex(line[9:-3])
			data += b
			
			prev_addr = current_addr + data_len
			
		elif rec_type == 2:
			seg_addr = int(line[9:-3], 16)
			continue
		elif rec_type == 4:
			lin_addr = int(line[9:-3], 16)
			continue
		else:
			# should be EOF
			return data

	return data


def parse_motolora_hex(fin):

	met_data = False
	data = bytearray()
	prev_addr = 0
	index = 0
	for line in fin:
		index += 1
		rec_type = line[1]

		if rec_type == '1':
			data_start_index = 8			
		elif rec_type == '2':
			data_start_index = 10
		elif rec_type == '3':
			data_start_index = 12
		else:
			continue

		data_len = int(line[2:4], 16) - 4
		current_addr = int(line[4:data_start_index], 16)
		if met_data and current_addr > prev_addr:
			for i in range(current_addr - prev_addr):
				data.append(0xFF)

		met_data = True
		b = binascii.a2b_hex(line[data_start_index:-3])
		data += b
		
		prev_addr = current_addr + data_len


	return data


def main(argv):

	# get and check input file
	if len(argv) < 2:
		print('input file name required')
		return
	
	fin_name = argv[1]
	if not os.path.isfile(fin_name):
		print('file not found')
		return


	# get output file path and name
	fout_name = None

	if len(argv) > 2:
		fout_path = argv[2]
		if fout_path.rfind('.') > 0:
			fout_name = fout_path
		else:
			if fout_path[-1] != '\\' and fout_path != '/':
				fout_path += '\\'
			fout_name = fout_path + os.path.splitext(os.path.split(fin_name)[1])[0] + '.bin'
	else:
		fout_name = '.\\' + os.path.splitext(os.path.split(fin_name)[1])[0] + '.bin'

	print('binary data will be written to file %s' %fout_name)

	# parse hex file
	fin = open(fin_name)
	line = fin.readline()
	fmt = line[0]
	fin.close()
	
	with open(fin_name) as fin:
		if fmt == ':':
			data = parse_intel_hex(fin)
			fout = open(fout_name, 'wb')
			fout.write(data)
			fout.close()
			print('0x%x bytes retrieved from file of intel format' % len(data))
		elif fmt == 'S':
			data = parse_motolora_hex(fin)
			fout = open(fout_name, 'wb')
			fout.write(data)
			fout.close()
			print('0x%x bytes retrieved from file of motolora format' % len(data))
		else:
			print('unknown data format')


if __name__ == '__main__':
	#main(sys.argv)
	argv = ['', '.\\angle2.hex']
	main(argv)
	